import { io, Socket } from 'socket.io-client'

/**
 * Socket.IO连接管理器
 */
class SocketManager {
  private socket: Socket | null = null
  private userId: number | null = null
  private reconnectAttempts = 0
  private maxReconnectAttempts = 5
  private isConnecting = false
  private heartbeatTimer: NodeJS.Timeout | null = null
  private onlineStatusCallbacks: Map<string, Function> = new Map()

  // 连接状态回调
  private connectionStateCallbacks: Map<string, Function> = new Map()

  // 连接状态枚举
  public readonly ConnectionState = {
    DISCONNECTED: 'disconnected',
    CONNECTING: 'connecting',
    CONNECTED: 'connected',
    RECONNECTING: 'reconnecting',
    FAILED: 'failed'
  } as const

  private currentState: string = this.ConnectionState.DISCONNECTED

  /**
   * 设置连接状态并通知监听器
   */
  private setConnectionState(state: string) {
    if (this.currentState !== state) {
      this.currentState = state
      console.log(`🔄 Socket连接状态变更: ${state}`)

      // 通知所有监听器
      this.connectionStateCallbacks.forEach(callback => {
        try {
          callback(state, this.reconnectAttempts)
        } catch (error) {
          console.error('连接状态回调执行失败:', error)
        }
      })
    }
  }

  /**
   * 监听连接状态变化
   */
  onConnectionStateChange(key: string, callback: (state: string, reconnectAttempts: number) => void) {
    this.connectionStateCallbacks.set(key, callback)
  }

  /**
   * 移除连接状态监听器
   */
  offConnectionStateChange(key: string) {
    this.connectionStateCallbacks.delete(key)
  }

  /**
   * 获取当前连接状态
   */
  getConnectionState() {
    return {
      state: this.currentState,
      reconnectAttempts: this.reconnectAttempts,
      isConnected: this.socket?.connected || false
    }
  }

  /**
   * 连接Socket.IO服务器
   */
  connect(userId: number): Promise<void> {
    return new Promise((resolve, reject) => {
      if (this.socket && this.socket.connected) {
        // console.log('🔗 Socket已连接，无需重复连接')
        this.setConnectionState(this.ConnectionState.CONNECTED)
        resolve()
        return
      }

      if (this.isConnecting) {
        // console.log('🔗 Socket正在连接中...')
        return
      }

      this.isConnecting = true
      this.userId = userId

      // 设置连接状态
      if (this.reconnectAttempts === 0) {
        this.setConnectionState(this.ConnectionState.CONNECTING)
      } else {
        this.setConnectionState(this.ConnectionState.RECONNECTING)
      }

      // console.log('🚀 开始连接Socket.IO服务器...', { userId })

      this.socket = io('http://localhost:9092', {
        query: {
          userId: userId.toString()
        },
        transports: ['websocket', 'polling'],
        timeout: 10000,
        reconnection: true,
        reconnectionAttempts: this.maxReconnectAttempts,
        reconnectionDelay: 1000,
        reconnectionDelayMax: 5000
      })

      // 连接成功
      this.socket.on('connect', () => {
        console.log('✅ Socket.IO连接成功', {
          socketId: this.socket?.id,
          userId: this.userId
        })
        this.isConnecting = false
        this.reconnectAttempts = 0
        this.setConnectionState(this.ConnectionState.CONNECTED)
        console.log('✅ 实时连接已建立')
        resolve()
      })

      // 连接失败
      this.socket.on('connect_error', (error) => {
        console.error('❌ Socket.IO连接失败:', error)
        this.isConnecting = false
        this.reconnectAttempts++

        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
          console.error('❌ 无法连接到实时服务，请检查网络连接')
          this.setConnectionState(this.ConnectionState.FAILED)
          reject(error)
        } else {
          // 还有重连机会，设置为重连状态
          this.setConnectionState(this.ConnectionState.RECONNECTING)
        }
      })

      // 断开连接
      this.socket.on('disconnect', (reason) => {
        console.log('🔌 Socket.IO连接断开:', reason)
        this.isConnecting = false
        this.setConnectionState(this.ConnectionState.DISCONNECTED)

        if (reason === 'io server disconnect') {
          // 服务器主动断开，需要手动重连
          this.reconnect()
        }
      })

      // 重连尝试开始
      this.socket.on('reconnect_attempt', (attemptNumber) => {
        console.log(`🔄 Socket.IO重连尝试 ${attemptNumber}/${this.maxReconnectAttempts}`)
        this.setConnectionState(this.ConnectionState.RECONNECTING)
      })

      // 重连成功
      this.socket.on('reconnect', (attemptNumber) => {
        console.log('✅ Socket.IO重连成功:', attemptNumber)
        console.log('✅ 实时连接已恢复')
        this.reconnectAttempts = 0
        this.setConnectionState(this.ConnectionState.CONNECTED)
      })

      // 重连失败
      this.socket.on('reconnect_failed', () => {
        console.error('❌ Socket.IO重连失败')
        console.error('❌ 实时连接重连失败')
        this.setConnectionState(this.ConnectionState.FAILED)
      })

      // 服务器消息
      this.socket.on('connected', (data) => {
        console.log('📨 收到服务器连接确认:', data)
        // 开始心跳
        this.startHeartbeat()

        // 连接确认后立即发送一次心跳
        setTimeout(() => {
          if (this.socket && this.socket.connected) {
            this.socket.emit('heartbeat', {
              timestamp: Date.now(),
              userId: this.userId
            })
          }
        }, 500)
      })

      this.socket.on('error', (data) => {
        console.error('❌ 服务器错误:', data)
        console.error('❌ 服务器错误:', data.message || '服务器错误')
      })

      // 用户在线状态相关事件
      this.setupOnlineStatusListeners()
    })
  }

  /**
   * 手动重连
   */
  private reconnect() {
    if (this.userId && this.reconnectAttempts < this.maxReconnectAttempts) {
      // console.log('🔄 尝试重连Socket.IO...', this.reconnectAttempts + 1)
      setTimeout(() => {
        this.connect(this.userId!)
      }, 2000)
    }
  }

  /**
   * 断开连接
   */
  disconnect() {
    if (this.socket) {
      this.stopHeartbeat()
      this.socket.disconnect()
      this.socket = null
      this.userId = null
      this.reconnectAttempts = 0
      this.isConnecting = false
      this.onlineStatusCallbacks.clear()
      // console.log('🔌 Socket.IO连接已断开')
    }
  }

  /**
   * 发送事件
   */
  emit(event: string, data?: any) {
    if (this.socket && this.socket.connected) {
      this.socket.emit(event, data)
      console.log('📤 发送Socket事件:', event, data)
    } else {
      console.warn('⚠️ Socket未连接，无法发送事件:', event, data)
    }
  }

  /**
   * 监听事件
   */
  on(event: string, callback: (data: any) => void) {
    if (this.socket) {
      this.socket.on(event, callback)
      // console.log('👂 监听Socket事件:', event)
    }
  }

  /**
   * 取消监听事件
   */
  off(event: string, callback?: (data: any) => void) {
    if (this.socket) {
      this.socket.off(event, callback)
      // console.log('🔇 取消监听Socket事件:', event)
    }
  }

  /**
   * 获取连接状态
   */
  get isConnected(): boolean {
    const connected = this.socket?.connected || false
    // 只在状态变化时打印日志，避免过多输出
    if (this.lastLoggedState !== connected) {
      console.log('🔍 Socket连接状态变化:', {
        hasSocket: !!this.socket,
        connected: connected,
        currentState: this.currentState,
        userId: this.userId
      })
      this.lastLoggedState = connected
    }
    return connected
  }

  private lastLoggedState: boolean | null = null

  /**
   * 获取Socket ID
   */
  get socketId(): string | undefined {
    return this.socket?.id
  }

  /**
   * 开始心跳
   */
  private startHeartbeat() {
    this.stopHeartbeat()

    // 每30秒发送一次心跳
    this.heartbeatTimer = setInterval(() => {
      if (this.socket && this.socket.connected) {
        this.socket.emit('heartbeat', {
          timestamp: Date.now(),
          userId: this.userId
        })
      }
    }, 30000)
  }

  /**
   * 停止心跳
   */
  private stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
      this.heartbeatTimer = null
    }
  }

  /**
   * 设置在线状态事件监听器
   */
  private setupOnlineStatusListeners() {
    if (!this.socket) return

    // 心跳响应
    this.socket.on('heartbeatResponse', (data) => {
      // console.log('💓 收到心跳响应:', data)
    })

    // 用户状态变化
    this.socket.on('userStatusChanged', (data) => {
      console.log('👤 用户状态变化:', data)
      this.notifyOnlineStatusChange(data)
    })

    // 在线用户列表
    this.socket.on('onlineUsersList', (data) => {
      console.log('📋 在线用户列表:', data)
      this.notifyOnlineStatusChange({ type: 'onlineUsersList', data })
    })

    // 用户状态响应
    this.socket.on('userStatusResponse', (data) => {
      console.log('📊 用户状态响应:', data)
      this.notifyOnlineStatusChange({ type: 'userStatusResponse', data })
    })
  }

  /**
   * 获取在线用户列表
   */
  getOnlineUsers() {
    if (this.socket && this.socket.connected) {
      this.socket.emit('getOnlineUsers', {})
    }
  }

  /**
   * 获取指定用户状态
   */
  getUserStatus(userId: number) {
    if (this.socket && this.socket.connected) {
      this.socket.emit('getUserStatus', { userId })
    }
  }

  /**
   * 注册在线状态变化回调
   */
  onOnlineStatusChange(key: string, callback: Function) {
    this.onlineStatusCallbacks.set(key, callback)
  }

  /**
   * 取消在线状态变化回调
   */
  offOnlineStatusChange(key: string) {
    this.onlineStatusCallbacks.delete(key)
  }

  /**
   * 通知在线状态变化
   */
  private notifyOnlineStatusChange(data: any) {
    this.onlineStatusCallbacks.forEach(callback => {
      try {
        callback(data)
      } catch (error) {
        console.error('❌ 在线状态回调执行失败:', error)
      }
    })
  }
}

// 导出单例实例
export const socketManager = new SocketManager()
export default socketManager
